<!--
 * @Author: 张鹏
 * @Date: 2025-07-24
 * @LastEditors: fyukeeh 15849141465@163.com
 * @LastEditTime: 2025-07-29 17:04:28
 * @FilePath: \mapbox\src\views\example\MaterialDemo.vue
 * @Description: 材质自定义演示页面
-->
<template>
  <div class="map-page">
    <div id="map" class="map-container"></div>
    
    <!-- 使用MapToolbar组件 -->
    <MapToolbar 
      title="材质自定义工具" 
      :show-draw-buttons="true" 
      :draw-buttons="drawButtons" 
      btn-size="small"
      @removeAll="removeAllEntities" 
      @hideAll="hideAllEntities" 
      @showAll="showAllEntities"
      @toggleEdit="toggleEdit" 
    />
    
    <!-- 材质信息弹窗 -->
    <el-dialog
      v-model="materialDialogVisible"
      title="材质信息"
      width="500px"
      :before-close="closeMaterialDialog"
    >
      <div v-if="selectedEntity" class="material-info">
        <div class="entity-info">
          <h4>实体类型：{{ selectedEntity.type }}</h4>
          <p>ID：{{ selectedEntity.id }}</p>
        </div>
        
        <el-divider />
        
        <div class="current-material">
          <h4>当前材质</h4>
          <div class="material-preview">
            <div 
              class="color-preview" 
              :style="{ backgroundColor: currentMaterial.color || '#3388ff' }"
            ></div>
            <div class="material-details">
              <p><strong>颜色：</strong>{{ currentMaterial.color || '#3388ff' }}</p>
              <p><strong>透明度：</strong>{{ currentMaterial.opacity || 1 }}</p>
              <p v-if="currentMaterial.width"><strong>宽度：</strong>{{ currentMaterial.width }}</p>
              <p v-if="currentMaterial.borderColor"><strong>边框颜色：</strong>{{ currentMaterial.borderColor }}</p>
              <p v-if="currentMaterial.borderWidth"><strong>边框宽度：</strong>{{ currentMaterial.borderWidth }}</p>
            </div>
          </div>
        </div>
        
        <el-divider />
        
        <div class="material-options">
          <h4>材质选项</h4>
          
          <!-- 颜色选择 -->
          <div class="option-group">
            <label>颜色：</label>
            <el-color-picker 
              v-model="editingMaterial.color" 
              show-alpha
              @change="previewMaterial"
            />
          </div>
          
          <!-- 透明度滑块 -->
          <div class="option-group">
            <label>透明度：</label>
            <el-slider 
              v-model="editingMaterial.opacity" 
              :min="0" 
              :max="1" 
              :step="0.1"
              @change="previewMaterial"
            />
          </div>
          
          <!-- 宽度滑块 -->
          <div v-if="supportsWidth" class="option-group">
            <label>宽度：</label>
            <el-slider 
              v-model="editingMaterial.width" 
              :min="1" 
              :max="50" 
              :step="1"
              @change="previewMaterial"
            />
          </div>
          
          <!-- 边框颜色选择 -->
          <div v-if="supportsBorder" class="option-group">
            <label>边框颜色：</label>
            <el-color-picker 
              v-model="editingMaterial.borderColor" 
              show-alpha
              @change="previewMaterial"
            />
          </div>
          
          <!-- 边框宽度滑块 -->
          <div v-if="supportsBorder" class="option-group">
            <label>边框宽度：</label>
            <el-slider 
              v-model="editingMaterial.borderWidth" 
              :min="1" 
              :max="10" 
              :step="1"
              @change="previewMaterial"
            />
          </div>
          
          <!-- 预设材质 -->
          <div class="preset-materials">
            <h5>预设材质</h5>
            <div class="preset-grid">
              <div 
                v-for="(preset, index) in materialPresets" 
                :key="index"
                class="preset-item"
                :style="{ backgroundColor: preset.color }"
                @click="applyPreset(preset)"
              >
                <span class="preset-name">{{ preset.name }}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
      
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="cancelEdit">取消</el-button>
          <el-button @click="resetMaterial">重置</el-button>
          <el-button type="primary" @click="confirmEdit">确定</el-button>
        </span>
      </template>
    </el-dialog>
    
    <!-- 说明信息 -->
    <div class="info-panel">
      <h3>材质自定义演示</h3>
      <p>1. 使用工具栏绘制实体</p>
      <p>2. 点击已绘制的实体查看材质信息</p>
      <p>3. 在弹窗中修改材质属性（实时预览）</p>
      <p>4. 点击"确定"保存修改，或"取消"放弃修改</p>
      <p>5. 支持颜色、透明度、宽度、边框等属性</p>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, computed } from 'vue'
import Map from '289-map'
import MapToolbar from '@/components/MapToolbar.vue'
import {
  Edit,
  Location,
  Aim,
  Monitor,
  Document,
  CircleCheck
} from '@element-plus/icons-vue'

// 响应式数据
const map = ref(null)
const entities = ref([])
const materialDialogVisible = ref(false)
const selectedEntity = ref(null)
const editingMaterial = reactive({
  color: '#3388ff',
  opacity: 1,
  width: 20,
  borderColor: '#000000',
  borderWidth: 2
})

// 当前材质（只读）
const currentMaterial = computed(() => {
  return selectedEntity.value?.style || {}
})

// 是否支持宽度属性
const supportsWidth = computed(() => {
  if (!selectedEntity.value) return false
  return ['Point', 'Line', 'StraightArrow', 'AttackArrow', 'DoubleArrow', 'SwallowtailArrow', 'BottomCurveArrow'].includes(selectedEntity.value.type)
})

// 是否支持边框属性
const supportsBorder = computed(() => {
  if (!selectedEntity.value) return false
  return ['Rectangle', 'Polygon', 'GatheringPlace'].includes(selectedEntity.value.type)
})

// 绘制工具配置
const drawButtons = computed(() => [
  {
    label: '点',
    type: 'default',
    icon: CircleCheck,
    onClick: () => draw('Point')
  },
  {
    label: '线',
    type: 'default',
    icon: Edit,
    onClick: () => draw('Line')
  },
  {
    label: '面',
    type: 'default',
    icon: Monitor,
    onClick: () => draw('Polygon')
  },
  {
    label: '矩形',
    type: 'default',
    icon: Monitor,
    onClick: () => draw('Rectangle')
  },
  {
    label: '标记点',
    type: 'primary',
    icon: Location,
    onClick: () => draw('BillboardEntity')
  },
  {
    label: '标签',
    type: 'primary',
    icon: Document,
    onClick: () => draw('Label')
  },
  {
    label: '直线箭头',
    type: 'default',
    icon: Aim,
    onClick: () => draw('StraightArrow')
  },
  {
    label: '攻击箭头',
    type: 'default',
    icon: Aim,
    onClick: () => draw('AttackArrow')
  },
  {
    label: '双箭头',
    type: 'default',
    icon: Aim,
    onClick: () => draw('DoubleArrow')
  },
  {
    label: '燕尾箭头',
    type: 'default',
    icon: Aim,
    onClick: () => draw('SwallowtailArrow')
  },
  {
    label: '底部曲线箭头',
    type: 'default',
    icon: Aim,
    onClick: () => draw('BottomCurveArrow')
  },
  {
    label: '集结地',
    type: 'primary',
    icon: Monitor,
    onClick: () => draw('GatheringPlace')
  }
])

// 预设材质
const materialPresets = [
  { name: '默认蓝', color: '#3388ff', opacity: 1, width: 20 },
  { name: '红色', color: '#ff0000', opacity: 0.8, width: 20 },
  { name: '绿色', color: '#00ff00', opacity: 0.8, width: 20 },
  { name: '黄色', color: '#ffff00', opacity: 0.8, width: 20 },
  { name: '紫色', color: '#800080', opacity: 0.8, width: 20 },
  { name: '橙色', color: '#ffa500', opacity: 0.8, width: 20 },
  { name: '半透明', color: '#3388ff', opacity: 0.5, width: 20 },
  { name: '粗线条', color: '#ff0000', opacity: 1, width: 40 }
]

// 初始化地图
onMounted(async () => {
  map.value = new Map('map', {
    style: 'https://demotiles.maplibre.org/style.json',
    scene: {
      center: { lng: 116.397, lat: 39.916 },
      zoom: 10
    },
    controller: ['showZoom', 'showCompass']
  })

  // 监听地图点击事件
  map.value.on('click', handleMapClick)
})

// 绘制函数
const draw = async (type) => {
  let graphic;
  
  if (type === 'BillboardEntity') {
    graphic = map.value.startDraw({
      type: 'BillboardEntity',
      style: {
        image: await import('@/assets/images.jpg'),
        width: 32,
        height: 32,
        label: {
          text: '标记点',
          color: '#ffffff',
          background: 'rgba(0,0,0,0.7)'
        }
      },
      onDrawEnd: (entity) => {
        if (entity) {
          entity.click = () => showMaterialDialog(entity)
          entities.value.push(entity)
        }
      }
    })
  } else if (type === 'Label') {
    graphic = map.value.startDraw({
      type: 'Label',
      style: {
        text: '标签',
        color: '#ffffff',
        background: 'rgba(0,0,0,0.8)',
        padding: '4px 8px'
      },
      onDrawEnd: (entity) => {
        if (entity) {
          entity.click = () => showMaterialDialog(entity)
          entities.value.push(entity)
        }
      }
    })
  } else {
    // 其他实体类型
    graphic = map.value.startDraw({
      type: type,
      style: getDefaultStyle(type),
      onDrawEnd: (entity) => {
        if (entity) {
          entity.click = () => showMaterialDialog(entity)
          entities.value.push(entity)
        }
      }
    })
  }
}

// 获取默认样式
const getDefaultStyle = (type) => {
  const baseStyle = {
    color: '#3388ff',
    opacity: 0.8,
    width: 20
  }
  
  switch (type) {
    case 'Point':
      return { ...baseStyle, width: 20 }
    case 'Line':
      return { ...baseStyle, width: 4 }
    case 'Polygon':
      return { ...baseStyle, opacity: 0.4 }
    case 'Rectangle':
      return { 
        ...baseStyle, 
        color: '#ff8800',
        borderColor: '#000000',
        borderWidth: 2
      }
    case 'StraightArrow':
    case 'AttackArrow':
    case 'DoubleArrow':
    case 'SwallowtailArrow':
    case 'BottomCurveArrow':
      return { 
        ...baseStyle, 
        color: '#ff0000',
        outlineColor: '#000000'
      }
    case 'GatheringPlace':
      return { 
        ...baseStyle, 
        color: '#FFD700',
        opacity: 0.5
      }
    default:
      return baseStyle
  }
}

// 处理地图点击
const handleMapClick = (e) => {
  // 检查是否点击了实体
  const features = map.value.queryRenderedFeatures(e.point)
  if (features.length > 0) {
    const feature = features[0]
    // 查找对应的实体
    let entity = entities.value.find(e => e.id === feature.source)
    
    // 如果没有在entities中找到，尝试从地图的实体管理器中查找
    if (!entity && map.value._entityManager) {
      entity = map.value._entityManager.entities.find(e => e.id === feature.source)
    }
    
    // 如果还是没有找到，尝试通过图层ID查找
    if (!entity) {
      const layerId = feature.layer?.id
      if (layerId) {
        entity = entities.value.find(e => e.id === layerId || e.id === layerId.replace('-outline', '').replace('-border', ''))
      }
    }
    
    if (entity) {
      showMaterialDialog(entity)
    }
  }
}

// 显示材质对话框
const showMaterialDialog = (entity) => {
  selectedEntity.value = entity
  // 复制当前材质到编辑区域
  Object.assign(editingMaterial, {
    color: entity.style?.color || '#3388ff',
    opacity: entity.style?.opacity || 1,
    width: entity.style?.width || 20,
    borderColor: entity.style?.borderColor || entity.style?.outlineColor || '#000000',
    borderWidth: entity.style?.borderWidth || 2
  })
  materialDialogVisible.value = true
}

// 更新材质
const updateMaterial = () => {
  if (!selectedEntity.value) return
  
  // 更新实体样式
  if (!selectedEntity.value.style) {
    selectedEntity.value.style = {}
  }
  
  Object.assign(selectedEntity.value.style, {
    color: editingMaterial.color,
    opacity: editingMaterial.opacity,
    width: editingMaterial.width
  })
  
  // 处理边框属性
  if (supportsBorder.value) {
    selectedEntity.value.style.borderColor = editingMaterial.borderColor
    selectedEntity.value.style.borderWidth = editingMaterial.borderWidth
  } else if (['StraightArrow', 'AttackArrow', 'DoubleArrow', 'SwallowtailArrow', 'BottomCurveArrow'].includes(selectedEntity.value.type)) {
    selectedEntity.value.style.outlineColor = editingMaterial.borderColor
  }
  
  // 重新渲染实体
  if (typeof selectedEntity.value.render === 'function' && map.value) {
    selectedEntity.value.render(map.value)
  }
  
  // 对于MapLibre GL图层，需要手动更新图层样式
  if (map.value && selectedEntity.value.id) {
    try {
      // 更新主图层
      if (map.value.getLayer(selectedEntity.value.id)) {
        const paint = {}
        if (selectedEntity.value.style.color) {
          if (map.value.getLayer(selectedEntity.value.id).type === 'circle') {
            paint['circle-color'] = selectedEntity.value.style.color
            paint['circle-opacity'] = selectedEntity.value.style.opacity || 1
            if (selectedEntity.value.style.width) {
              paint['circle-radius'] = selectedEntity.value.style.width / 2
            }
          } else if (map.value.getLayer(selectedEntity.value.id).type === 'line') {
            paint['line-color'] = selectedEntity.value.style.color
            paint['line-opacity'] = selectedEntity.value.style.opacity || 1
            if (selectedEntity.value.style.width) {
              paint['line-width'] = selectedEntity.value.style.width
            }
          } else if (map.value.getLayer(selectedEntity.value.id).type === 'fill') {
            paint['fill-color'] = selectedEntity.value.style.color
            paint['fill-opacity'] = selectedEntity.value.style.opacity || 1
          }
        }
        
        // 应用样式
        Object.keys(paint).forEach(key => {
          map.value.setPaintProperty(selectedEntity.value.id, key, paint[key])
        })
      }
      
      // 更新边框图层
      if (map.value.getLayer(selectedEntity.value.id + '-border')) {
        const borderPaint = {}
        if (selectedEntity.value.style.borderColor) {
          borderPaint['line-color'] = selectedEntity.value.style.borderColor
          borderPaint['line-opacity'] = selectedEntity.value.style.borderOpacity || 1
        }
        if (selectedEntity.value.style.borderWidth) {
          borderPaint['line-width'] = selectedEntity.value.style.borderWidth
        }
        
        Object.keys(borderPaint).forEach(key => {
          map.value.setPaintProperty(selectedEntity.value.id + '-border', key, borderPaint[key])
        })
      }
      
      // 更新描边图层
      if (map.value.getLayer(selectedEntity.value.id + '-outline')) {
        const outlinePaint = {}
        if (selectedEntity.value.style.outlineColor) {
          outlinePaint['fill-color'] = selectedEntity.value.style.outlineColor
          outlinePaint['fill-opacity'] = selectedEntity.value.style.opacity || 1
        }
        
        Object.keys(outlinePaint).forEach(key => {
          map.value.setPaintProperty(selectedEntity.value.id + '-outline', key, outlinePaint[key])
        })
      }
    } catch (error) {
      console.warn('更新图层样式失败:', error)
    }
  }
}

// 应用预设材质
const applyPreset = (preset) => {
  Object.assign(editingMaterial, preset)
  previewMaterial()
}

// 重置材质
const resetMaterial = () => {
  const defaultStyle = getDefaultStyle(selectedEntity.value.type)
  Object.assign(editingMaterial, defaultStyle)
  previewMaterial()
}

// 预览材质（实时更新）
const previewMaterial = () => {
  if (!selectedEntity.value) return
  
  // 临时更新实体样式进行预览
  const originalStyle = { ...selectedEntity.value.style }
  
  if (!selectedEntity.value.style) {
    selectedEntity.value.style = {}
  }
  
  Object.assign(selectedEntity.value.style, {
    color: editingMaterial.color,
    opacity: editingMaterial.opacity,
    width: editingMaterial.width
  })
  
  // 处理边框属性
  if (supportsBorder.value) {
    selectedEntity.value.style.borderColor = editingMaterial.borderColor
    selectedEntity.value.style.borderWidth = editingMaterial.borderWidth
  } else if (['StraightArrow', 'AttackArrow', 'DoubleArrow', 'SwallowtailArrow', 'BottomCurveArrow'].includes(selectedEntity.value.type)) {
    selectedEntity.value.style.outlineColor = editingMaterial.borderColor
  }
  
  // 更新MapLibre GL图层样式进行预览
  if (map.value && selectedEntity.value.id) {
    try {
      // 更新主图层
      if (map.value.getLayer(selectedEntity.value.id)) {
        const paint = {}
        if (selectedEntity.value.style.color) {
          if (map.value.getLayer(selectedEntity.value.id).type === 'circle') {
            paint['circle-color'] = selectedEntity.value.style.color
            paint['circle-opacity'] = selectedEntity.value.style.opacity || 1
            if (selectedEntity.value.style.width) {
              paint['circle-radius'] = selectedEntity.value.style.width / 2
            }
          } else if (map.value.getLayer(selectedEntity.value.id).type === 'line') {
            paint['line-color'] = selectedEntity.value.style.color
            paint['line-opacity'] = selectedEntity.value.style.opacity || 1
            if (selectedEntity.value.style.width) {
              paint['line-width'] = selectedEntity.value.style.width
            }
          } else if (map.value.getLayer(selectedEntity.value.id).type === 'fill') {
            paint['fill-color'] = selectedEntity.value.style.color
            paint['fill-opacity'] = selectedEntity.value.style.opacity || 1
          }
        }
        
        // 应用样式
        Object.keys(paint).forEach(key => {
          map.value.setPaintProperty(selectedEntity.value.id, key, paint[key])
        })
      }
      
      // 更新边框图层
      if (map.value.getLayer(selectedEntity.value.id + '-border')) {
        const borderPaint = {}
        if (selectedEntity.value.style.borderColor) {
          borderPaint['line-color'] = selectedEntity.value.style.borderColor
          borderPaint['line-opacity'] = selectedEntity.value.style.borderOpacity || 1
        }
        if (selectedEntity.value.style.borderWidth) {
          borderPaint['line-width'] = selectedEntity.value.style.borderWidth
        }
        
        Object.keys(borderPaint).forEach(key => {
          map.value.setPaintProperty(selectedEntity.value.id + '-border', key, borderPaint[key])
        })
      }
      
      // 更新描边图层
      if (map.value.getLayer(selectedEntity.value.id + '-outline')) {
        const outlinePaint = {}
        if (selectedEntity.value.style.outlineColor) {
          outlinePaint['fill-color'] = selectedEntity.value.style.outlineColor
          outlinePaint['fill-opacity'] = selectedEntity.value.style.opacity || 1
        }
        
        Object.keys(outlinePaint).forEach(key => {
          map.value.setPaintProperty(selectedEntity.value.id + '-outline', key, outlinePaint[key])
        })
      }
    } catch (error) {
      console.warn('预览图层样式失败:', error)
    }
  }
}

// 关闭材质对话框
const closeMaterialDialog = () => {
  materialDialogVisible.value = false
  selectedEntity.value = null
}

// MapToolbar 事件处理函数
const removeEntity = () => {
  // 删除选中的实体
  if (selectedEntity.value) {
    selectedEntity.value.remove(map.value)
    const index = entities.value.findIndex(e => e.id === selectedEntity.value.id)
    if (index > -1) {
      entities.value.splice(index, 1)
    }
    closeMaterialDialog()
  }
}

const removeAllEntities = () => {
  entities.value.forEach(entity => {
    entity.remove(map.value)
  })
  entities.value = []
  closeMaterialDialog()
}

const hideAllEntities = () => {
  entities.value.forEach(entity => {
    entity.show = false
  })
}

const showAllEntities = () => {
  entities.value.forEach(entity => {
    entity.show = true
  })
}

const toggleEdit = () => {
  entities.value.forEach(entity => {
    entity.edit = !entity.edit
  })
}

// 确认编辑材质
const confirmEdit = () => {
  updateMaterial()
  closeMaterialDialog()
}

// 取消编辑材质
const cancelEdit = () => {
  closeMaterialDialog()
}
</script>

<style lang="scss" scoped>
.map-page {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

.map-container {
  width: 100%;
  height: 100%;
}

.info-panel {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 1000;
  background: rgba(255, 255, 255, 0.95);
  border-radius: 8px;
  padding: 16px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
  max-width: 300px;
  
  h3 {
    margin: 0 0 12px 0;
    color: #333;
  }
  
  p {
    margin: 4px 0;
    color: #666;
    font-size: 14px;
  }
}

.material-info {
  .entity-info {
    margin-bottom: 16px;
    
    h4 {
      margin: 0 0 8px 0;
      color: #333;
    }
    
    p {
      margin: 4px 0;
      color: #666;
    }
  }
  
  .current-material {
    margin-bottom: 16px;
    
    h4 {
      margin: 0 0 12px 0;
      color: #333;
    }
    
    .material-preview {
      display: flex;
      align-items: center;
      gap: 12px;
      
      .color-preview {
        width: 40px;
        height: 40px;
        border-radius: 8px;
        border: 2px solid #ddd;
      }
      
      .material-details {
        flex: 1;
        
        p {
          margin: 4px 0;
          color: #666;
        }
      }
    }
  }
  
  .material-options {
    .option-group {
      margin-bottom: 16px;
      
      label {
        display: block;
        margin-bottom: 8px;
        color: #333;
        font-weight: 500;
      }
    }
    
    .preset-materials {
      margin-top: 20px;
      
      h5 {
        margin: 0 0 12px 0;
        color: #333;
      }
      
      .preset-grid {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
        gap: 12px;
        
        .preset-item {
          height: 40px;
          border-radius: 6px;
          display: flex;
          align-items: center;
          justify-content: center;
          cursor: pointer;
          border: 2px solid transparent;
          transition: all 0.2s;
          
          &:hover {
            border-color: #409eff;
            transform: scale(1.05);
          }
          
          .preset-name {
            color: #fff;
            font-size: 12px;
            font-weight: 500;
            text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
          }
        }
      }
    }
  }
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}
</style>